CloudFormationのDependsOn属性を使ってAPI Throttlingエラーを防止する
こんにちは、ジョン・ヒョンジェです。
CloudFormationでは一つのスタックに同じリソースをたくさん作成しようとすると、過度なAPIコールが発生してリソースの作成に失敗する可能性があります。
例として、一つのスタックで数十個のDynamoDBテーブルを作成している場合、DynamoDB APIへの過度なコールによるAPI Throttlingエラーが発生し、テーブルの作成に失敗してしまいます。そのため、DynamoDBでは同時に作成できるテーブルの数を50個に制限しています。DynamoDBだけではなくEC2インスタンスなど他のリソースも同じ理由で、あまりにも多くの数を作成しようとするとエラーが出る恐れがあります。
このようなAPI Throttlingエラーを防止するために、CloudFormationのDependsOn
属性を使うことができます。今回はその話をしていきたいと思います。
DependsOn属性について
CloudFormationでリソースを作成するときに、DependsOn属性を使ってリソースの作成順序を設定することができます。
以下のコードを用いて説明いたします。(AWSドキュメントから抜粋)
AWSTemplateFormatVersion: '2010-09-09' Mappings: RegionMap: us-east-1: AMI: ami-0ff8a91507f77f867 us-west-1: AMI: ami-0bdb828fd58c52235 eu-west-1: AMI: ami-047bb4163c506cd98 ap-northeast-1: AMI: ami-06cd52961ce9f0d85 ap-southeast-1: AMI: ami-08569b978cc4dfa10 Resources: Ec2Instance: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - AMI DependsOn: myDB myDB: Type: AWS::RDS::DBInstance Properties: AllocatedStorage: '5' DBInstanceClass: db.t2.small Engine: MySQL EngineVersion: '5.5' MasterUsername: MyName MasterUserPassword: MyPassword
DependsOn属性を利用すると、特定のリソースが他のリソースの次に作成されるように指定できます。このコードでは「Ec2Instance」というEC2インスタンスにDependsOn: myDB
と指定していて、「Ec2Instance」は「myDB」というRDSインスタンスを作成した後に作成し始めます。
特定の順序で作成や削除する必要があるリソースがある場合に、DependsOn属性を使ってリソースの依存関係を明示的に指定することができます。
この特性を利用して、先ほどお話ししたAPI Throttlingエラーを防ぐこともできます。では、DependsOn属性を使ってみます。
やってみよう
CloudFormationテンプレートを以下のように作成します。(テンプレートの作成はYAMLでします)
AWSTemplateFormatVersion: "2010-09-09" Resources: myTable1: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: "UserId" AttributeType: "S" - AttributeName: "UserName" AttributeType: "S" KeySchema: - AttributeName: "UserId" KeyType: "HASH" - AttributeName: "UserName" KeyType: "RANGE" ProvisionedThroughput: ReadCapacityUnits: "5" WriteCapacityUnits: "5" TableName: "myTable1" myTable2: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: "UserId" AttributeType: "S" - AttributeName: "UserName" AttributeType: "S" KeySchema: - AttributeName: "UserId" KeyType: "HASH" - AttributeName: "UserName" KeyType: "RANGE" ProvisionedThroughput: ReadCapacityUnits: "5" WriteCapacityUnits: "5" TableName: "myTable2" . . . myTable51: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: "UserId" AttributeType: "S" - AttributeName: "UserName" AttributeType: "S" KeySchema: - AttributeName: "UserId" KeyType: "HASH" - AttributeName: "UserName" KeyType: "RANGE" ProvisionedThroughput: ReadCapacityUnits: "5" WriteCapacityUnits: "5" TableName: "myTable51"
「myTable1」から「myTable51」まで、51個のテーブルを作成しています。
このテンプレートを使ってスタックを作成してみると、以下のようなエラーが出てスタック作成に失敗します。
Subscriber limit exceeded: Only 50 tables can be created, updated, or deleted simultaneously
DynamoDBではAPI Throttlingを防止するために、同時に作成できるテーブルの数を50個に制限しています。では、各リソースにDependsOn属性を追加し、作成するテーブル数を100個にしてみます。
AWSTemplateFormatVersion: "2010-09-09" Resources: myTable1: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: "UserId" AttributeType: "S" - AttributeName: "UserName" AttributeType: "S" KeySchema: - AttributeName: "UserId" KeyType: "HASH" - AttributeName: "UserName" KeyType: "RANGE" ProvisionedThroughput: ReadCapacityUnits: "5" WriteCapacityUnits: "5" TableName: "myTable1" myTable2: Type: AWS::DynamoDB::Table DependsOn: myTable1 Properties: AttributeDefinitions: - AttributeName: "UserId" AttributeType: "S" - AttributeName: "UserName" AttributeType: "S" KeySchema: - AttributeName: "UserId" KeyType: "HASH" - AttributeName: "UserName" KeyType: "RANGE" ProvisionedThroughput: ReadCapacityUnits: "5" WriteCapacityUnits: "5" TableName: "myTable2" . . . myTable100: Type: AWS::DynamoDB::Table DependsOn: myTable99 Properties: AttributeDefinitions: - AttributeName: "UserId" AttributeType: "S" - AttributeName: "UserName" AttributeType: "S" KeySchema: - AttributeName: "UserId" KeyType: "HASH" - AttributeName: "UserName" KeyType: "RANGE" ProvisionedThroughput: ReadCapacityUnits: "5" WriteCapacityUnits: "5" TableName: "myTable100"
各リソースにDependsOn属性を使って順序を指定しています。このテンプレートを使ってスタックを作成してみます。
同時ではなく順序通り次々とAPIを呼び出しますので時間が結構かかりますが、何のエラーもなく正常に100個のテーブルが作成されたのが確認できます。
最後に
DependsOn属性はリソース間の依存関係を指定するために使いますが、このようにAPI Throttlingエラーを防ぐための使い方もあります。実際にCloudFormationで同じリソースをこんなにたくさん作成する場合はほとんどないと思いますが、もし必要な場合は使ってみてください!
では、ブログは以上です。ありがとうございます。